package com.cwj.util;

import com.cwj.exception.NumberOverFlowerException;


/**
 * 数值计算结果溢出检测工具类
 * @author chenwujie
 * @date 2020/11/1210:02
 */
public class CheckNumberOverFlowerUtils {
    private static final String FORMAT_STR = "a(%1$s): %2$d, b(%1$s): %3$d ; a %4$s b overFlower";

    public static void add(int a, int b){
        int c = a + b;
        boolean overFlower = isOverFlowerOfAdd(a, b, c);
        if(overFlower){
            String type = "int";
            String operation = "+";
            throw new NumberOverFlowerException(String.format(FORMAT_STR, type, a, b, operation));
        }
    }

    public static void add(long a, long b){
        long c = a + b;
        boolean overFlower = (a > 0 && b > 0 && c <= 0) || (a < 0 && b < 0 && c >= 0);
        if(overFlower){
            String type = "long";
            String operation = "+";
            throw new NumberOverFlowerException(String.format(FORMAT_STR, type, a, b, operation));
        }
    }

    public static void multiply(int a, int b){
        int c = a * b;
        if(c == 0){
            return;
        }
        boolean overFlower = isOverFlowerOfMultiply(a, b, c);
        if(overFlower){
            String type = "int";
            String operation = "*";
            throw new NumberOverFlowerException(String.format(FORMAT_STR, type, a, b, operation));
        }
    }

    public static void multiply(long a, long b){
        long c = a * b;
        if(c == 0){
            return;
        }
        boolean overFlower = isOverFlowerOfMultiply(a, b, c);
        if(overFlower){
            String type = "long";
            String operation = "*";
            throw new NumberOverFlowerException(String.format(FORMAT_STR, type, a, b, operation));
        }
    }

    public static void divide(int a, int b){
        int c = a / b;
        if(c == 0){
            return;
        }
        boolean overFlower = isOverFlowerOfDivide(a, b, c);
        if(overFlower){
            String type = "int";
            String operation = "/";
            throw new NumberOverFlowerException(String.format(FORMAT_STR, type, a, b, operation));
        }
    }

    public static void divide(long a, long b){
        long c = a / b;
        if(c == 0){
            return;
        }
        boolean overFlower = isOverFlowerOfDivide(a, b, c);
        if(overFlower){
            String type = "long";
            String operation = "/";
            throw new NumberOverFlowerException(String.format(FORMAT_STR, type, a, b, operation));
        }
    }

    private static boolean isOverFlowerOfAdd(int a, int b, int c) {
        return  (a > 0 && b > 0 && c <= 0) || (a < 0 && b < 0 && c >= 0);
    }
    private static boolean isOverFlowerOfAdd(long a, long b, long c) {
        return (a > 0 && b > 0 && c <= 0) || (a < 0 && b < 0 && c >= 0);
    }
    private static boolean isOverFlowerOfMultiply(int a, int b, int c) {
//        return !(a == 0 || (c / a == b));
        return a != 0 && (c / a != b);
    }
    private static boolean isOverFlowerOfMultiply(long a, long b, long c) {
        return a != 0 && (c / a != b);
    }
    private static boolean isOverFlowerOfDivide(int a, int b, int c) {
        return (a == Integer.MIN_VALUE && b == -1) || (a == -1 && b == Integer.MIN_VALUE);
    }
    private static boolean isOverFlowerOfDivide(long a, long b, long c) {
        return (a == Long.MIN_VALUE && b == -1) || (a == -1 && b == Long.MIN_VALUE);
    }


}
